package renderer;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.component.behavior.ClientBehavior;
import javax.faces.component.behavior.ClientBehaviorContext;
import javax.faces.component.behavior.ClientBehaviorContext.Parameter;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.FacesRenderer;
import javax.faces.render.Renderer;

import custom.UITree;
import dto.FolderDTO;
import dto.RepositoryDTO;
import dto.ResourceDTO;

@FacesRenderer(componentFamily = "tree", rendererType = "renderer.TreeRender")
public class TreeRender extends Renderer 
{
	
	
	
	public TreeRender(){
	}
	
	
	private ArrayList<FolderDTO> folderz;
	private ArrayList<ResourceDTO> resourcez;
	private RepositoryDTO repository;
	private static int selected;
	
	
	@Override
	public void encodeBegin(FacesContext context, UIComponent component) throws IOException{
		if ((context == null) || (component == null)){
			throw new NullPointerException();
		}
		UITree tree = (UITree) component;
		//String adat = (String)tree.getAttributes().get("adat");
		ResponseWriter writer = context.getResponseWriter();
		writer.startElement("div", tree);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public void encodeChildren(FacesContext context, UIComponent component) throws IOException{
		if ((context == null) || (component == null)){
			throw new NullPointerException();
		}
		UITree tree = (UITree) component;
		ResponseWriter writer = context.getResponseWriter();
		folderz = (ArrayList<FolderDTO>)tree.getAttributes().get("flist");
		resourcez = (ArrayList<ResourceDTO>)tree.getAttributes().get("rlist");
		repository = (RepositoryDTO)tree.getAttributes().get("repository");
		printRepository(writer, tree, context);
		int root = Integer.parseInt(repository.getRepID());
		if(root != 0 && folderz != null && folderz.size() > 1){
			printFolderz(writer,root,tree,context);
		}
		writer.endElement("ul");
	}
	
	private void printRepository(ResponseWriter writer, UITree tree,FacesContext context) throws IOException{
		Map<String,List<ClientBehavior>> behaviors = tree.getClientBehaviors();
		writer.startElement("ul", tree);
		writer.startElement("li", tree);
		writer.startElement("div", tree);
		writer.writeAttribute("id", tree.getClientId(context), null);
		int rep = Integer.parseInt(repository.getRepID());
		if(selected == rep)
			writer.writeAttribute("class", "treeSelected", null);
		else
			writer.writeAttribute("class", "treeNotSelected", null);
		if(behaviors.containsKey("click")){
			ClientBehaviorContext behaviorContext = createOperationBehaviorContext(tree, context, rep, "repId");
			String click = behaviors.get("click").get(0).getScript(behaviorContext);
			writer.writeAttribute("onclick", click, null);
		}
		writer.startElement("img", tree);
		writer.writeAttribute("src", "./resources/images/repository.png", null);
		writer.writeAttribute("height", 20, null);
		writer.endElement("img");
		writer.write(repository.getRepName());
		
		writer.endElement("div");
		writer.endElement("li");
	}
	
	
	/**
	 * @author tokea
	 * @param writer
	 * @param parent
	 * @param tree
	 * @param context
	 * @throws IOException
	 */
	private void printFolderz(ResponseWriter writer,int parent, UITree tree,FacesContext context) throws IOException{
		Map<String,List<ClientBehavior>> behaviors = tree.getClientBehaviors();
		
		writer.startElement("ul", tree);
		for(FolderDTO f:folderz){
			if(f.getId_parent() == parent && f.getId() != parent){
				writer.startElement("li", tree);
				writer.startElement("div", tree);	
				if(selected == f.getId())
					writer.writeAttribute("class", "treeSelected", null);
					//writer.writeAttribute("style", "background:blue", null);
				else
					writer.writeAttribute("class", "treeNotSelected", null);
				if(hasChildren(f.getId())){
					writer.startElement("input", tree);
					writer.writeAttribute("type", "button", null);
					writer.writeAttribute("id", tree.getClientId(context), "id");
					writer.writeAttribute("name", f.getName(), null);
					if(behaviors.containsKey("click")){
						ClientBehaviorContext behaviorContext = createOperationBehaviorContext(tree, context, f.getId(), "fidExpand");
						String click = behaviors.get("click").get(0).getScript(behaviorContext);
						writer.writeAttribute("onclick", click, null);
					}
					if(f.isExpanded())
						writer.writeAttribute("value"," - ",null);
					else
						writer.writeAttribute("value"," + ",null);
					writer.endElement("input");
				}
				printFolderLabel(writer, parent, tree, context, f);
				if(f.isExpanded()){
					printFolderz(writer,f.getId(),tree,context);
				}
				writer.endElement("li");
			}
		}
		printResourcez(writer, parent, tree, context);
		writer.endElement("ul");
	}
	
	
	/**
	 * @author tokea
	 * @param writer
	 * @param parent
	 * @param tree
	 * @param context
	 * @param fol
	 * @throws IOException
	 */
	private void printFolderLabel(ResponseWriter writer,int parent, UITree tree,FacesContext context,FolderDTO fol)throws IOException{
		Map<String,List<ClientBehavior>> behaviors = tree.getClientBehaviors();
		
		
		if(behaviors.containsKey("click") ){
			ClientBehaviorContext behaviorContext = createOperationBehaviorContext(tree, context, fol.getId(), "fidNoExpand");
			String click = behaviors.get("click").get(0).getScript(behaviorContext);
			writer.writeAttribute("onclick", click, null);
		}
		writer.startElement("img", tree);
		writer.writeAttribute("src", "./resources/images/empty_folder.png", null);
		writer.writeAttribute("height", 20, null);
		writer.endElement("img");
		writer.write(fol.getName());
		writer.endElement("div");
	}
	
	
	/**
	 * @author tokea
	 * @param writer
	 * @param parent
	 * @param tree
	 * @param context
	 * @throws IOException
	 */
	private void printResourcez(ResponseWriter writer,int parent, UITree tree,FacesContext context) throws IOException{
		Map<String,List<ClientBehavior>> behaviors = tree.getClientBehaviors();
		
		for(ResourceDTO r:resourcez){
			if(r.getFolderId() == parent){
				writer.startElement("li", tree);
					writer.startElement("div", tree);
					if(selected == r.getId())
						writer.writeAttribute("class", "treeSelected", null);
						//writer.writeAttribute("style", "background:blue;", null);
					else
						writer.writeAttribute("class", "treeNotSelected", null);
					if(behaviors.containsKey("click")){
						ClientBehaviorContext behaviorContext = createOperationBehaviorContext(tree, context, r.getId(), "rid");
						String click = behaviors.get("click").get(0).getScript(behaviorContext);
						writer.writeAttribute("onclick", click, null);
					}
					writer.startElement("img", tree);
					if(r.getLockerId() == 1)
						writer.writeAttribute("src", "./resources/images/resource.png", null);
					else
						writer.writeAttribute("src", "./resources/images/resource_locked.png", null);
					writer.writeAttribute("height", 25, null);
					writer.endElement("img");
					writer.write(r.getName());
					writer.endElement("div");
				writer.endElement("li");
			}
		}
		
	}
	
	/**
	 * @author tokea
	 * @param tree
	 * @param context
	 * @param id
	 * @param opName
	 * @return ClientBehaviorContext
	 */
	private ClientBehaviorContext createOperationBehaviorContext( UITree tree,FacesContext context,int id,String opName){
		ArrayList<ClientBehaviorContext.Parameter> params = new ArrayList<ClientBehaviorContext.Parameter>();
		ClientBehaviorContext.Parameter p = new Parameter(opName,id);
		params.add(p);
		ClientBehaviorContext behaviorContext = ClientBehaviorContext.createClientBehaviorContext(context,tree, "click", tree.getClientId(context) , params);
		return behaviorContext;
	}
	
	@Override
	public void encodeEnd(FacesContext context, UIComponent component) throws IOException{
		if ((context == null) || (component == null)){
			throw new NullPointerException();
		}
		ResponseWriter writer = context.getResponseWriter();
		writer.endElement("div");
	}
	
	@Override
	public void decode(FacesContext context, UIComponent component){
		if ((context == null) || (component == null)){
			throw new NullPointerException();
		}

		UITree tree = (UITree) component;
		Map<String, List<ClientBehavior>> behaviors = tree.getClientBehaviors();
		if (behaviors.isEmpty()) 
			System.out.println("Behavior is empty");
		ExternalContext external = context.getExternalContext();
		Map<String, String> params = external.getRequestParameterMap();
		for(String s:params.keySet())
			System.out.println(s + " "+params.get(s));
		/* if(behaviorEvent != null){
    	   List<ClientBehavior> behaviorsForEvent = behaviors.get(behaviorEvent);
    	   System.out.println("Decoding some shit!");
    	   if(behaviors.size() > 0){
    		   String behaviorSource = params.get("javax.faces.source");
    		                   String clientId = tree.getClientId(context);
    		                  if (behaviorSource != null && behaviorSource.equals(clientId)) {

    		                       for (ClientBehavior behavior: behaviorsForEvent) {
    		                           behavior.decode(context, tree);
    		                       }
    		                   }
    	   }
       }*/
			
		
		if(params.containsValue("click")){
			int id = 0;
			if(params.containsKey("fidExpand") ){
				id = Integer.parseInt(params.get("fidExpand"));
				FolderDTO n = findFolder(id);
				if(n != null){
					n.setExpanded(!n.isExpanded());
					tree.setValue(n);
				}
			}else if(params.containsKey("rid")){
				id = Integer.parseInt(params.get("rid"));
				ResourceDTO r = findResource(id);
				if(r != null )
					tree.setValue(r);
			}else if(params.containsKey("fidNoExpand")){
				id = Integer.parseInt(params.get("fidNoExpand"));
				FolderDTO n = findFolder(id);
				tree.setValue(n);
			}else if(params.containsKey("repId")){
				id = Integer.parseInt(repository.getRepID());
				tree.setValue(repository);
			}
			selected = id;
		}
	}
	
	/**
	 * @author tokea
	 * @param id
	 * @return FolderDTO node
	 */
	private FolderDTO findFolder(int id){
		FolderDTO node = null;
		for(FolderDTO n:folderz){
			if(n.getId() == id){
				node = n;
				break;
			}
		}
		return node;
	}
	
	/**
	 * @author tokea
	 * @param id
	 * @return ResourceDTO node
	 */
	private ResourceDTO findResource(int id){
		ResourceDTO node = null;
		for(ResourceDTO r:resourcez){
			if(r.getId() == id){
				node = r;
				break;
			}
		}
		return node;
	}
	
	/**
	 * @author tokea
	 * @param id
	 * @return boolean has
	 */
	private boolean hasChildren(int id){
		boolean has = false;
		for(FolderDTO f:folderz)
			if(f.getId_parent() == id){
				has = true;
				break;
			}
		if(!has)
			for(ResourceDTO r:resourcez)
				if(r.getFolderId() == id){
					has = true;
					break;
				}
		return has;
	}
}
